"""
积分系统模块
提供积分的增加、查询、兑换等功能
"""

import json
from pathlib import Path
from typing import Dict, Any, List, Optional
from datetime import datetime
import uuid

# 积分数据存储路径
POINTS_DATA_PATH = Path(__file__).parent.parent / "data" / "user_points.json"

# 积分规则定义
POINTS_RULES = {
    "daily_login": {
        "points": 5,
        "description": "每日登录奖励",
        "limit": "daily"
    },
    "purchase": {
        "points": 1,  # 每元积1分
        "description": "购物消费",
        "limit": None
    },
    "profile_completion": {
        "points": 20,
        "description": "完善个人资料",
        "limit": "once"
    },
    "review": {
        "points": 10,
        "description": "商品评价",
        "limit": "per_item"
    },
    "share": {
        "points": 15,
        "description": "分享商品",
        "limit": "daily_limit_3"
    }
}

# 积分兑换选项
POINTS_REWARDS = [
    {
        "id": "discount_5",
        "name": "5元优惠券",
        "points_required": 100,
        "description": "满50元可用",
        "type": "coupon",
        "value": 5,
        "min_amount": 50
    },
    {
        "id": "discount_10",
        "name": "10元优惠券",
        "points_required": 200,
        "description": "满100元可用",
        "type": "coupon",
        "value": 10,
        "min_amount": 100
    },
    {
        "id": "discount_20",
        "name": "20元优惠券",
        "points_required": 400,
        "description": "满200元可用",
        "type": "coupon",
        "value": 20,
        "min_amount": 200
    },
    {
        "id": "free_shipping",
        "name": "免运费券",
        "points_required": 150,
        "description": "任意订单可用",
        "type": "free_shipping"
    },
    {
        "id": "points_double",
        "name": "积分翻倍卡",
        "points_required": 300,
        "description": "7天内购物积分翻倍",
        "type": "points_boost",
        "multiplier": 2.0,
        "duration_days": 7
    },
    {
        "id": "mystery_box",
        "name": "神秘礼盒",
        "points_required": 500,
        "description": "随机获得精美礼品",
        "type": "mystery_gift"
    },
    {
        "id": "birthday_gift",
        "name": "生日礼品包",
        "points_required": 800,
        "description": "精美生日礼品+200积分",
        "type": "special_gift",
        "bonus_points": 200
    }
]

def _initialize_points_data():
    """初始化积分数据文件"""
    if not POINTS_DATA_PATH.exists():
        default_data = {
            "points": {},
            "transactions": [],
            "rewards_claimed": []
        }
        with open(POINTS_DATA_PATH, 'w', encoding='utf-8') as f:
            json.dump(default_data, f, ensure_ascii=False, indent=2)
        return default_data
    
    try:
        with open(POINTS_DATA_PATH, 'r', encoding='utf-8') as f:
            return json.load(f)
    except Exception as e:
        print(f"读取积分数据文件失败: {e}")
        return {
            "points": {},
            "transactions": [],
            "rewards_claimed": []
        }

def _save_points_data(data: Dict[str, Any]) -> bool:
    """保存积分数据"""
    try:
        # 确保父目录存在
        POINTS_DATA_PATH.parent.mkdir(parents=True, exist_ok=True)
        
        with open(POINTS_DATA_PATH, 'w', encoding='utf-8') as f:
            json.dump(data, f, ensure_ascii=False, indent=2)
        return True
    except Exception as e:
        print(f"保存积分数据失败: {e}")
        return False

def get_user_points(user_id: str) -> int:
    """获取用户积分余额"""
    data = _initialize_points_data()
    return data["points"].get(user_id, 0)

def get_user_points_history(user_id: str) -> List[Dict[str, Any]]:
    """获取用户积分交易记录"""
    data = _initialize_points_data()
    return [tx for tx in data["transactions"] if tx["user_id"] == user_id]

def add_points(user_id: str, points: int, reason: str, activity_type: str = None, reference_id: str = None) -> bool:
    """
    给用户添加积分
    
    参数:
        user_id: 用户ID
        points: 积分数量(正数为增加,负数为减少)
        reason: 积分变动原因描述
        activity_type: 活动类型(可选,用于限制某些活动的积分获取频率)
        reference_id: 关联ID(如订单ID、评论ID等)
    """
    if points == 0:
        return True  # 积分为0,无需操作
    
    data = _initialize_points_data()
    
    # 检查活动类型限制
    if activity_type and activity_type in POINTS_RULES:
        rule = POINTS_RULES[activity_type]
        limit_type = rule.get("limit")
        
        # 检查该用户的历史记录
        user_transactions = [tx for tx in data["transactions"] if tx["user_id"] == user_id]
        
        if limit_type == "once":
            # 检查是否已经获得过这种类型的积分
            if any(tx["activity_type"] == activity_type for tx in user_transactions):
                return False  # 已经获得过一次性奖励
        
        elif limit_type == "daily":
            # 检查今天是否已经获得过这种类型的积分
            today = datetime.now().strftime("%Y-%m-%d")
            if any(tx["activity_type"] == activity_type and tx["timestamp"].startswith(today) for tx in user_transactions):
                return False  # 今天已经获得过每日奖励
        
        elif limit_type == "per_item" and reference_id:
            # 检查是否已经为此特定项目获得过积分
            if any(tx["activity_type"] == activity_type and tx["reference_id"] == reference_id for tx in user_transactions):
                return False  # 已经为此项目获得过积分
        
        elif limit_type and limit_type.startswith("daily_limit_"):
            # 每日限制次数
            try:
                limit_count = int(limit_type.split("_")[-1])
                today = datetime.now().strftime("%Y-%m-%d")
                today_count = sum(1 for tx in user_transactions 
                                if tx["activity_type"] == activity_type and tx["timestamp"].startswith(today))
                
                if today_count >= limit_count:
                    return False  # 已达到每日限制次数
            except ValueError:
                pass  # 格式错误,不做限制
    
    # 更新积分余额
    current_points = data["points"].get(user_id, 0)
    new_points = current_points + points
    
    if new_points < 0:
        return False  # 积分不足,无法扣减
    
    data["points"][user_id] = new_points
    
    # 记录交易
    transaction = {
        "id": str(uuid.uuid4()),
        "user_id": user_id,
        "points": points,
        "reason": reason,
        "activity_type": activity_type,
        "reference_id": reference_id,
        "timestamp": datetime.now().isoformat()
    }
    
    data["transactions"].append(transaction)
    
    # 保存数据
    return _save_points_data(data)

def claim_reward(user_id: str, reward_id: str) -> Dict[str, Any]:
    """
    兑换积分奖励
    
    参数:
        user_id: 用户ID
        reward_id: 奖励ID
    
    返回:
        包含成功/失败状态和消息的字典
    """
    # 查找奖励信息
    reward = None
    for r in POINTS_REWARDS:
        if r["id"] == reward_id:
            reward = r
            break
    
    if not reward:
        return {"success": False, "message": "奖励不存在"}
    
    # 检查用户积分是否足够
    user_points = get_user_points(user_id)
    points_required = reward["points_required"]
    
    if user_points < points_required:
        return {"success": False, "message": f"积分不足,需要{points_required}积分,当前积分{user_points}"}
    
    # 扣减积分
    if not add_points(user_id, -points_required, f"兑换奖励: {reward['name']}", "reward_claim", reward_id):
        return {"success": False, "message": "积分扣减失败"}
    
    # 根据奖励类型处理
    result_message = f"成功兑换 {reward['name']}"
    additional_info = {}
    
    if reward["type"] == "coupon":
        # 发放优惠券
        try:
            from utils.coupon_system import issue_coupon
            coupon_result = issue_coupon(
                user_id=user_id,
                coupon_type="coupon",
                value=reward["value"],
                min_amount=reward["min_amount"],
                validity_days=30,
                source="points_exchange"
            )
            if coupon_result["success"]:
                additional_info["coupon_id"] = coupon_result["coupon_id"]
                result_message += f"，优惠券已发放到您的账户"
            else:
                result_message += f"，但优惠券发放失败"
        except ImportError:
            result_message += f"，但优惠券系统不可用"
    
    elif reward["type"] == "free_shipping":
        # 发放免运费券
        try:
            from utils.coupon_system import issue_coupon
            coupon_result = issue_coupon(
                user_id=user_id,
                coupon_type="free_shipping",
                value=0,
                min_amount=0,
                validity_days=30,
                source="points_exchange"
            )
            if coupon_result["success"]:
                additional_info["coupon_id"] = coupon_result["coupon_id"]
                result_message += f"，免运费券已发放到您的账户"
            else:
                result_message += f"，但免运费券发放失败"
        except ImportError:
            result_message += f"，但优惠券系统不可用"
    
    elif reward["type"] == "special_gift":
        # 特殊礼品（如生日礼品包）
        if reward.get("bonus_points", 0) > 0:
            add_points(user_id, reward["bonus_points"], f"奖励礼品包额外奖励", "gift_bonus")
            result_message += f"，并获得{reward['bonus_points']}积分奖励"
        additional_info["gift_type"] = "birthday_package"
    
    elif reward["type"] == "points_boost":
        # 积分翻倍卡等功能性奖励
        additional_info["boost_type"] = "points_double"
        additional_info["duration_days"] = reward.get("duration_days", 7)
        additional_info["multiplier"] = reward.get("multiplier", 2.0)
        result_message += f"，{reward.get('duration_days', 7)}天积分翻倍生效"
    
    elif reward["type"] == "mystery_gift":
        # 神秘礼盒
        additional_info["mystery_gift"] = True
        result_message += f"，神秘礼品将在3-5个工作日内配送"
    
    # 记录兑换
    data = _initialize_points_data()
    claimed_reward = {
        "id": str(uuid.uuid4()),
        "user_id": user_id,
        "reward_id": reward_id,
        "reward_name": reward["name"],
        "reward_type": reward["type"],
        "points_cost": points_required,
        "timestamp": datetime.now().isoformat(),
        "status": "active",  # active, used, expired
        "additional_info": additional_info
    }
    
    data["rewards_claimed"].append(claimed_reward)
    _save_points_data(data)
    
    return {
        "success": True,
        "message": result_message,
        "reward": claimed_reward,
        "additional_info": additional_info
    }

def get_user_rewards(user_id: str) -> List[Dict[str, Any]]:
    """获取用户已兑换的奖励"""
    data = _initialize_points_data()
    return [reward for reward in data["rewards_claimed"] if reward["user_id"] == user_id]

def daily_login(user_id: str) -> Dict[str, Any]:
    """处理用户每日登录奖励"""
    result = add_points(
        user_id=user_id,
        points=POINTS_RULES["daily_login"]["points"],
        reason=POINTS_RULES["daily_login"]["description"],
        activity_type="daily_login"
    )
    
    if result:
        return {
            "success": True,
            "message": f"获得{POINTS_RULES['daily_login']['points']}积分的每日登录奖励!",
            "points": POINTS_RULES["daily_login"]["points"]
        }
    else:
        return {
            "success": False,
            "message": "今天已经领取过登录奖励",
            "points": 0
        }

def add_purchase_points(user_id: str, order_id: str, amount: float) -> Dict[str, Any]:
    """处理购物积分奖励"""
    points_to_add = int(amount * POINTS_RULES["purchase"]["points"])
    
    if points_to_add <= 0:
        return {"success": False, "message": "订单金额过小,无法获得积分", "points": 0}
    
    result = add_points(
        user_id=user_id,
        points=points_to_add,
        reason=f"{POINTS_RULES['purchase']['description']}: ¥{amount:.2f}",
        activity_type="purchase",
        reference_id=order_id
    )
    
    if result:
        return {
            "success": True,
            "message": f"购物获得{points_to_add}积分!",
            "points": points_to_add
        }
    else:
        return {
            "success": False,
            "message": "积分添加失败",
            "points": 0
        }

def get_available_rewards() -> List[Dict[str, Any]]:
    """获取所有可用的积分兑换选项"""
    return POINTS_REWARDS
